package club.emergency.wechat.staff.operate.provider.impl;

import club.emergency.wechat.common.response.ResponseEntity;
import club.emergency.wechat.common.response.StatusCode;
import club.emergency.wechat.model.staff.Staff;
import club.emergency.wechat.model.wechat_api.UserInfo;
import club.emergency.wechat.model.wechat_api.UserInfoSimple;
import club.emergency.wechat.persistence.staff.StaffMapper;
import club.emergency.wechat.redis.RedisOperation;
import club.emergency.wechat.redis.common.RedisKeyConstant;
import club.emergency.wechat.staff.operate.StaffOperate;
import club.emergency.wechat.staff.operate.provider.service.WechatApiConsumer;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import net.javacrumbs.shedlock.core.SchedulerLock;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Create with IntelliJ IDEA
 * Project Name: wechat
 * Package Name: club.emergency.wechat.staff.operate.provider.impl
 * Date: 2018/11/16
 *
 * @author: 快乐的小菌菌
 * Description:
 */
@Slf4j
@RestController
@Transactional(rollbackFor = Exception.class)
public class StaffOperateImpl implements StaffOperate {

    private WechatApiConsumer wechatApiConsumer;

    private ExecutorService executorService;

    private StaffMapper staffMapper;

    private RedisOperation<Staff> redisOperation;

    public StaffOperateImpl(WechatApiConsumer wechatApiConsumer, ExecutorService executorService, StaffMapper staffMapper, RedisOperation<Staff> redisOperation) {
        this.wechatApiConsumer = wechatApiConsumer;
        this.executorService = executorService;
        this.staffMapper = staffMapper;
        this.redisOperation = redisOperation;
    }

    @Override
    public String save(@RequestBody Staff staff) {
        staffMapper.insert(staff);
        return ResponseEntity.ok(StatusCode.DB_SAVE_OK, "数据存储成功", staff.getId());
    }

    @Override
    public String modify(@RequestBody Staff staff) {
        staffMapper.updateById(staff);
        String openId = staff.getOpenId();
        String key = RedisKeyConstant.STAFF_OPENID + openId;
        Staff newStaff = redisOperation.get(key, Staff.class);
        redisOperation.add(key, newStaff, 3, TimeUnit.HOURS);
        return ResponseEntity.ok(StatusCode.DB_MODIFY_OK, "用户更新成功", staff.getId());
    }

    @Override
    public String unBind(@RequestParam("openId") String openId) {
        QueryWrapper<Staff> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("open_id", openId);
        staffMapper.update(new Staff().setPhone(""), queryWrapper);
        String key = RedisKeyConstant.STAFF_OPENID + openId;
        Staff newStaff = redisOperation.get(key, Staff.class);
        redisOperation.add(key, newStaff, 3, TimeUnit.HOURS);
        return ResponseEntity.ok(StatusCode.DB_MODIFY_OK, "微信手机号解绑成功！");
    }

    @Override
    public String signIn(@RequestParam("id") Long id, @RequestParam("openId") String openId) {
        Staff staff = new Staff();
        staff.setId(id);
        staff.setSignIn(1);
        staffMapper.updateById(staff);
        redisOperation.delete(RedisKeyConstant.STAFF_OPENID + openId);
        return ResponseEntity.ok(StatusCode.DB_MODIFY_OK, "微信签到成功！");
    }

    @Override
    public String updateEachTest(@RequestParam("id") Long id, @RequestParam("openId") String openId) {
        Staff staff = new Staff();
        staff.setId(id);
        staff.setEachTest(1);
        staffMapper.updateById(staff);
        redisOperation.delete(RedisKeyConstant.STAFF_OPENID + openId);
        return ResponseEntity.ok(StatusCode.DB_MODIFY_OK, "更新每日答题状态成功！");
    }

    @Scheduled(cron = "0 0 0 * * ?")
    @SchedulerLock(name = "shedLock_refreshSignIn")
    public void refreshSignIn() {
        log.info("<=======刷新签到、每日答题方法执行========>");
        Staff staff = new Staff();
        staff.setSignIn(0);
        staff.setEachTest(0);
        staffMapper.update(staff, null);
        List<String> keyList = redisOperation.likeKeys(RedisKeyConstant.STAFF_OPENID);
        if (Objects.nonNull(keyList)) {
            redisOperation.deleteKeyList(keyList);
        }
        log.info("<=======刷新签到、每日答题成功========>");
    }

    /**
     * 定时更新用户信息
     */
    @Scheduled(cron = "0 0 0/1 * * ?")
    @SchedulerLock(name = "shedLock_refreshStaffInfo")
    public void refreshStaffInfo() {
        log.info("<=======刷新人员微信端数据方法执行========>");
        int pageSize = 50;
        Integer staffCount = staffMapper.selectCount(null);
        if (staffCount.equals(0)) {
            return;
        }
        //计算线程个数
        int threadCount = staffCount / pageSize;
        for (int i = 0; i <= threadCount; i++) {
            int finalI = i;
            executorService.submit(() -> {
                Page<Staff> page = new Page<>(finalI + 1, pageSize);
                QueryWrapper<Staff> queryWrapper = new QueryWrapper<>();
                queryWrapper.orderByAsc("id");
                IPage<Staff> staffIPage = staffMapper.selectPage(page, queryWrapper);
                List<Staff> staffList = staffIPage.getRecords();
                UserInfoSimple userInfoSimple = new UserInfoSimple();
                if (staffList.size() == 0) {
                    return;
                }
                staffList.forEach(staff -> userInfoSimple.userInnerInfo(staff.getOpenId()));
                List<UserInfo> userInfoList = wechatApiConsumer.getUserInfoList(userInfoSimple);
                userInfoList.forEach(userInfo -> staffList.forEach(staff -> {
                    if (userInfo.getOpenid().equals(staff.getOpenId())) {
                        staff.setNickname(userInfo.getNickname());
                        staff.setSex(userInfo.getSex());
                        staff.setLanguage(userInfo.getLanguage());
                        staff.setCity(userInfo.getCity());
                        staff.setProvince(userInfo.getProvince());
                        staff.setCountry(userInfo.getCountry());
                        staff.setHeadimgurl(userInfo.getHeadimgurl());
                        staff.setSubscribeScene(userInfo.getSubscribeScene());
                        staffMapper.updateById(staff);
                    }
                }));
            });
        }
        log.info("<=======刷新人员微信端数据方法成功========>");
    }

}
